﻿using Idenmpotency;
using Microsoft.AspNetCore.Idenmpotency;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Yarp.ReverseProxy.Idenmptency
{
    /// <summary>
    /// Yarp幂等性中间件建造器
    /// </summary>
    public class YarpIdenmpotencyBuilder
    {
        public AspIdenmpotencyBuilder _builder;
        public YarpIdenmpotencyBuilder(AspIdenmpotencyBuilder builder)
        {
            this._builder = builder;
            this._builder.ResiterRequestFactory<YarpIdenmpotencyRequestFactory>();
        }

        /// <summary>
        /// 添加Yarp路由幂等性仓储
        /// </summary>
        /// <typeparam name="TRepository"></typeparam>
        /// <returns></returns>
        public YarpIdenmpotencyBuilder AddRouteIdenmpotencyRepository<TRepository>()
            where TRepository : class, IYarpRouteIdenmpotencyRepository
        {
            _builder.GetServiceCollection.AddSingleton<IYarpRouteIdenmpotencyRepository, TRepository>();
            return this;
        }

        /// <summary>
        /// 添加请求生成器
        /// </summary>
        /// <typeparam name="TGenerator"></typeparam>
        /// <param name="builder"></param>
        /// <returns></returns>
        public YarpIdenmpotencyBuilder AddIdenmpotencyRequestGenerator<TGenerator>()
            where TGenerator : class, IYarpIdenmpotencyRequestGenerator
        {
            _builder.GetServiceCollection.AddSingleton<IYarpIdenmpotencyRequestGenerator, TGenerator>();
            return this;
        }

        /// <summary>
        /// 注册幂等性请求记录的仓储
        /// </summary>
        /// <typeparam name="TRepository"></typeparam>
        /// <returns></returns>
        public YarpIdenmpotencyBuilder AddIdenmpotencyRequestRepository<TRepository>()
            where TRepository : class, IIdenmpotencyRequestRepositroy
        {
            _builder.UseRepository<TRepository>();
            return this;
        }

        /// <summary>
        /// 注册幂等性检查处理器
        /// </summary>
        /// <typeparam name="THandler"></typeparam>
        /// <returns></returns>
        public YarpIdenmpotencyBuilder AddHandler<THandler>()
            where THandler : class, IAspIdenmptencyRequestHandler
        {
            _builder.ResiterHandler<THandler>();
            return this;
        }

        /// <summary>
        /// 是否注册异常检测
        /// </summary>
        /// <typeparam name="TItem"></typeparam>
        /// <exception cref="IdenmpotencyException"></exception>
        private void IsRegister<TItem>()
        {
            var result = _builder.GetServiceCollection
                .Where(sd => sd.ServiceType == typeof(TItem))
                .Any();
            if (!result)
            {
                throw new IdenmpotencyException($"{typeof(TItem)}实例未注册");
            }
        }

        /// <summary>
        /// 建造
        /// </summary>
        public void Build()
        {
            _builder.Build();
            try
            {
                IsRegister<IYarpRouteIdenmpotencyRepository>();
                IsRegister<IYarpIdenmpotencyRequestGenerator>();
            }
            catch (IdenmpotencyException e)
            {
                throw e;
            }
        }
    }



}
